package org.xqh.study.google.guava.math;

import com.google.common.math.DoubleMath;
import com.google.common.math.IntMath;
import org.junit.Test;

import java.math.RoundingMode;

/**
 * 数值运算
 * 1、IntMath
 * 2、LongMath
 * 3、BigIntegerMath
 * 4、DoubleMath
 */
public class MathTest {

    //IntMath
    @Test
    public void testIntMath() {
        //该方法是检查一个整数是不是可以换算成2的指数，也就是检查转换成2进制之后是不是只有一个1。
        System.out.println(IntMath.isPowerOfTwo(4));

        //该方法是返回一个整数基于2的对数，使用mode来取整。
        System.out.println(IntMath.log2(4, RoundingMode.DOWN));

        //该方法是返回一个整数基于10的对数，使用mode来取整。
        System.out.println(IntMath.log10(4, RoundingMode.DOWN));

        //该方法返回的是以b为底，以k为指数的值；如果他们大小超过了整数范围，它就相当于BigInteger.valueOf(b).pow(k).intValue()。
        System.out.println(IntMath.pow(2, 4));

        //该方法整数的开平方根，根据mode模式取整。
        System.out.println(IntMath.sqrt(4, RoundingMode.DOWN));

        //该方法返回p除以q的值，按照mode模式取整。
        System.out.println(IntMath.divide(4, 3, RoundingMode.DOWN));

        //该方法返回的是x%m的值，但是和他的区别是，这个方法返回的总是非负数。
        System.out.println(IntMath.mod(4, 2));

        //该方法返回的是两个整数a和b的最大公因数，如果a == b == 0，那么返回0.
        System.out.println(IntMath.gcd(4, 7));

        //该方法返回的是整数a和整数b的和，如果和不超过整数范围，就返回这个值。
        System.out.println(IntMath.checkedAdd(4, 8));

        //该方法是返回整数a和整数b的差，如果不超过整数范围，就返回这个值。
        System.out.println(IntMath.checkedSubtract(4, 3));

        //该方法返回整数a和整数b的乘积，如果不超过整数返回，就返回这个值。
        System.out.println(IntMath.checkedMultiply(4, 2));

        //该方法返回以b为底，以k为指数的幂，如果不超过整数范围，就返回这个值。
        System.out.println(IntMath.checkedPow(4, 2));

        //该方法返回的是n的阶乘，如果n == 0，则返回1，如果最后结果已经超过了整数最大值，就返回整数的最大值。
        System.out.println(IntMath.factorial(4));

        //该方法是返回排列组合中的组合的值，相当于，如果超过整数的最大值，将会返回整数的最大值。
        System.out.println(IntMath.binomial(4, 2));
    }

    //LongMath
    @Test
    public void testLongMath() {
        //该类是针对long类型的数进行算术运算。该类中的方法和IntMath中的方法一样，只不过把IntMath中的int类型改为long就可以了。具体的方法解析不再一一介绍。
    }

    //DoubleMath
    @Test
    public void testDoubleMath() {
        //该方法是将double类型的数按照mode方式取整。
        System.out.println(DoubleMath.roundToInt(2.2, RoundingMode.DOWN));

        //该方法是将double类型的数x按照mode方式取整，返回long类型的数。
        System.out.println(DoubleMath.roundToLong(2.2, RoundingMode.DOWN));

        //该方法是将double类型的数x按照mode的方式取整，然后返回BigInteger类型的数。
        System.out.println(DoubleMath.roundToBigInteger(2.2, RoundingMode.DOWN));

        //该方法功能是，如果x严格等于2的k次幂，就返回true，否则返回false。
        System.out.println(DoubleMath.isPowerOfTwo(2.2));

        //该方法返回以2为底的对数。
        System.out.println(DoubleMath.log2(2.2));

        //该方法功能是，对于x，计算他以2为底的对数，然后按照mode方式取整，并返回。
        System.out.println(DoubleMath.log2(2.2, RoundingMode.DOWN));

        //该方法是判断当前的double 类型的值x是否也是一个整数，如果是返回true，否则返回false，当前前提这个数必须是有穷的和有限的。
        System.out.println(DoubleMath.isMathematicalInteger(2.2));

        //该方法返回的是n的阶乘，如果最后的值超过Double的最大值，就会返回Double.POSITIVE.INFINITY。
        System.out.println(DoubleMath.factorial(2));

        //该方法是比较两个double类型的数是否在一定范围内相等，即a和b的差的绝对值是否小于tolerance，如果小于，返回true，否则返回false。
        System.out.println(DoubleMath.fuzzyEquals(2.2, 3.3, 4.4));

        //该方法是比较两个double类型的数，如果在一定范围内相等，就返回0，如果a > b，就返回1， 如果a < b就返回-1，否则返回Booleans.compare(Double.isNaN(a),Double.isNaN(b));这是针对所有的NaN的值。
        System.out.println(DoubleMath.fuzzyCompare(2.2, 3.3, 4.4));

    }

    //BigIntegerMath
    @Test
    public void testBigIntegerMath() {
        //该类是针对BigInteger类型的数进行操作运算的，该类中包含的方法有binomial(), divide(), factorial(), isPowerOfTwo(), log10(), log2(),sqrt()，这些方法在IntMath类中都出现过，把所有的int类型替换成BigInteger类型就可以了，不在做一一介绍。
    }

}
